home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Utilities / Winter Shell 1.0d2 / Source / Libraries / FileLib / FileCreateDeleteLib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-17  |  5.3 KB  |  190 lines  |  [TEXT/KAHL]

  1. /* Functions for creating, deleting, and renaming files.
  2.  
  3.     93/10/20 aih
  4.     - FileUnique now checks for folder name conflicts as well, and made
  5.     file name construction a little more intelligent so that it can be
  6.     used with user-visible files.
  7.     
  8.     93/10/14 aih
  9.     - an existing file is no longer deleted before creating a new file
  10.     
  11.     93/03/26 AIH
  12.     - Added function to get a unique file name in a list of directories
  13.     
  14.     91/05/15 AIH
  15.     - Added some comments
  16.     - Made maximum file length for unique files 14 chars
  17.     
  18.     91/05/06 Ari Halberstadt (AIH)
  19.     - Fixed bug in FileUnique. */
  20.  
  21. #include <limits.h>
  22. #include <stdarg.h>
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include "pstr.h"
  26. #include "MathLib.h"
  27. #include "StringLib.h"
  28. #include "FileLib.h"
  29. #include "FolderLib.h"
  30.  
  31. /* delete the file */
  32. void FileDelete(FileType *fp)
  33. {
  34.     require(FileValid(fp));
  35.     FailOSErr(HDelete(fp->vol, fp->dir, fp->pnm));
  36. }
  37.  
  38. /* erase the either the data or the resource fork of the file, whichever
  39.     is open */
  40. static void FileEraseFork(FileType *fp)
  41. {
  42.     char buffer[FILE_BUFSIZ];
  43.     FilePosType size;
  44.     FilePosType    count;
  45.     
  46.     require(FileValid(fp));
  47.     require(fp->ref != FILE_CLOSED);    
  48.     memclr(buffer, FILE_BUFSIZ);
  49.     size = FileSize(fp);
  50.     while (size > 0) {
  51.         count = min(size, FILE_BUFSIZ);
  52.         size -= count;
  53.         FileWrite(fp, count, buffer);
  54.     }
  55. }
  56.  
  57. /* erase the data fork */
  58. static void FileEraseData(FileType *fp)
  59. {
  60.     TRY {
  61.         FileOpen(fp, fsWrPerm);
  62.         FileEraseFork(fp);
  63.     } CLEANUP {
  64.         FileClose(fp);
  65.     } ENDTRY;
  66. }
  67.  
  68. /* erase the resource fork */
  69. static void FileEraseRes(FileType *fp)
  70. {
  71.     TRY {
  72.         FileOpenRes(fp, fsWrPerm);
  73.         FileEraseFork(fp);
  74.     } CLEANUP {
  75.         FileClose(fp);
  76.     } ENDTRY;
  77. }
  78.  
  79. /* Erase both forks of the file by writing over them with zeroes.
  80.     This is more secure than just deleting a file since the operating
  81.     system just removes the reference to the file, not the actual data.
  82.     You may want to call this function more than once to ensure that
  83.     all the data are completely erased (various devices are capable of
  84.     reading the faint signals that remain on erased disks). You should
  85.     also beware of files which may have shrunk, or which have changed
  86.     the sectors they are on, since the unused sectors may still contain
  87.     valuable data which are not erased by this function. */
  88. void FileErase(FileType *fp)
  89. {
  90.     FileEraseData(fp);
  91.     FileEraseRes(fp);
  92. }
  93.  
  94. /* create the file using the specified creator and type */
  95. void FileCreate(FileType *fp, OSType creator, OSType type)
  96. {
  97.     FailOSErr(HCreate(fp->vol, fp->dir, fp->pnm, creator, type));
  98. }
  99.  
  100. /* Rename the file. The file parameter (fp) is updated accordingly. */
  101. void FileRename(FileType *fp, const FileNameType name)
  102. {
  103.     FilePNameType newname;
  104.  
  105.     require(FileValid(fp));
  106.     require(StrValid(name, sizeof(FileNameType)));    
  107.     FailOSErr(HRename(fp->vol, fp->dir, fp->pnm, c2pstrcpy(newname, name)));
  108.     FileNameSet(fp, name);
  109. }
  110.  
  111. /* This is the almost the same as FileUnique, but it will generate a file
  112.     name which is unique in all of the specified directories. The name
  113.     field of the directory specifications is ignored. The last directory
  114.     should be NULL. The parameters following 'orignm' should be of
  115.     type FileType, and contain the the directory specifications. */
  116. void FileUniqueInList(FileNameType orignm, ...)
  117. {
  118.     const short     maxtry = TMP_MAX;
  119.     const short     maxlen = sizeof(FileNameType); /* program_note: use 14 chars if need compatability with A/UX 1.0 */
  120.     FileType            file, *cfp = &file; /* file being checked */
  121.     FileType            *dirfp;    /* directory to check */
  122.     FileNameType    name;        /* file's name */
  123.     CStr31            num;        /* number we're trying */
  124.     short                try;        /* current number we're trying */
  125.     short                len;        /* length of name */
  126.     short                i;            /* index to directories */
  127.     va_list            ap;        /* for accessing the list of directories */
  128.     Boolean            found;    /* true if found a unique name */
  129.  
  130.     /* give a new numeric suffix to the file until either a unique
  131.         name is generated or the maximum number of attempts is exceeded */
  132.     check(0 < maxlen && maxlen <= sizeof(FileNameType));
  133.     check(0 < maxtry);
  134.     try = 0;
  135.     found = false;
  136.     strcpy(name, orignm);
  137.     do {
  138.  
  139.         /* check if a file with the name exists in any of the directories */
  140.         va_start(ap, orignm);
  141.         do {
  142.             dirfp = va_arg(ap, FileType *);
  143.             if (dirfp) {
  144.                 FileClone(dirfp, cfp);
  145.                 FileNameSet(cfp, name);
  146.             }
  147.         } while (dirfp && ! FileExists(cfp) && ! FolderExists(cfp));
  148.         va_end(ap);
  149.         found = (! dirfp);
  150.  
  151.         /* append numeric suffix, being careful with length of name */
  152.         if (! found) {
  153.             NumToString(try + 2, (StringPtr) num);
  154.             p2cstr((StringPtr) num);
  155.             check(maxlen > strlen(num) + 2);
  156.             len = maxlen - strlen(num) - 2;
  157.             strncpy(name, orignm, len);
  158.             name[len] = 0;
  159.             strcat(name, " ");
  160.             strcat(name, num);
  161.         }
  162.         
  163.     } while (! found && ++try < maxtry);
  164.     
  165.     if (! found) {
  166.         /* gave up */
  167.         check(try == maxtry);
  168.         FailOSErr(dupFNErr);
  169.     }
  170.     
  171.     strcpy(orignm, name);
  172. }
  173.  
  174. /* Generate a unique name for the file (useful for temporary files).
  175.     The unique file's name is of the form <Name><Number>, where <Name>
  176.     is the file's original name and <Number> is some unique integer.
  177.     The resulting file name is truncated to 14 characters to ensure
  178.     that it will be unique even on volumes created by A/UX 1.0 (see
  179.     TN229). If no unique file name could be generated then
  180.     dupFNErr is raised. */
  181. void FileUnique(FileType *fp)
  182. {
  183.     FileNameType name;
  184.     
  185.     strcpy(name, FileName(fp));
  186.     FileUniqueInList(name, fp, NULL);
  187.     FileNameSet(fp, name);
  188.     ensure(! FileExists(fp) && ! FolderExists(fp));
  189. }
  190.